<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of Category
 *
 * @author martin
 */
class setCategory extends CActiveRecord
{   
        public $result = null;      //返回处理结果
        public $values = null;      //计算结果属性
        const DEFAULTS = 1;         //默认值常量
        const TABLENAME = null;     
        public $params = array(     //动态属性
            'params'=>array(
                'post'=>null,
                'actions'=>null,
                'value'=>null,
            ),
        );

        public function __construct($params) 
        {
            foreach($params as $key=>$n)
            {
                if(array_key_exists($key, $this->params))
                        $this->params = (object)$n;
            }

            switch ($this->params->actions)
            {
                case $this->params->actions == 'create' :
                     $this->setCreate();
                     break;
                case $this->params->actions = 'delete' :
                     $this->setDelete();
                     break;
                case $this->params->actions = 'update' : 
                     $this->setUpdate();
                     break;
                case $this->params->actions = 'saveupdate':
                     $this->saveUpdate();
                     break;
                default : throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
            }
            
        }
    
        /**
         * 新增分类
         */
        public function setCreate()
        {
            if(0 < $this->params->post)
            {
                $model = Category::model()->find('LOWER(id)=?',array($this->params->post));
                $res = $this->_setleft($model->right);            
                $connection = Yii::app()->db;
                $transaction=$connection->beginTransaction();
                try
                {
                   $command = $connection->createCommand('UPDATE `category` SET `left` = `left` +2 WHERE `left` > '.$res)->execute();
                   $connection->createCommand('UPDATE `category` SET `right` = `right` +2 WHERE `right` > '.$res)->execute();
                   $transaction->commit();
                   (string)$this->values = $model->right;
                }
                catch(Exception $e)
                {
                   $transaction->rollBack();
                    throw new CHttpException(400,'因服务器原因,添加失败!');
                }                
            }
            else
            {
                (string)$this->values = $this->checkMax();  
            }
            
                $models=new Category;
                $models->name = $this->params->value['name'];
                $models->left =  $this->values;
                $models->right =  $this->values+1;
                $models->layout = $model->layout+1;
                $models->attributes=$models;
                if($models->save())
                        $this->result = $models->id;
                else
                    return false;
        }
        
        public function _setleft($id)
        {
            return ($id - self::DEFAULTS);
        }
        
        public function checkMax()
        {
            $res = Yii::app()->db->createCommand()
                ->select('right')
                ->from('category')
                ->order('right desc')
                ->limit(1)
                ->queryRow();
            if(!is_null($res['right']))
                return $res['right'];
            else
                return self::DEFAULTS;

        }
        
        /**
         * 删除分类
         */
        public function setDelete()
        {
            $res = array();
            $lar = $this->loadModel($this->params->post);
            $father = $this->setParent($lar);
            if($father == false)
            {
                if($this->setDownSun($lar->right))
                {
                    if(!is_null($lar))
                    {
                        $res = $lar->delete($this->params->post);
                        if($res)
                            (boolean)$this->result = true;
                        else 
                            (boolean)$this->result = false;                
                    }
                    else
                        throw new CHttpException(400,'id不存在!');
                }
                else
                    throw new CHttpException(400,'因服务器原因,删除失败!');
            }
            else
                throw new CHttpException(400,'存在下级分类,不能删除!');
        }
        
        
        /**
         *更新右值，升级大于他的左右值,减法
         * @param type $model father
         * @param type string is right value
         */
        public function setDownSun($right)
        {
            $connection = Yii::app()->db;
            $transaction=$connection->beginTransaction();
            try
            {
               $connection->createCommand('UPDATE `category` SET `left` = `left` -2 WHERE `left` > '.$right)->execute();
               $connection->createCommand('UPDATE `category` SET `right` = `right` -2 WHERE `right` > '.$right)->execute();
               $transaction->commit();
               return true;
            }
            catch(Exception $e)
            {
               $transaction->rollBack();
               return false;
            }
        }
        
        /**
         *更新右值，升级大于他的左右值,加法
         * @param type $model father
         * @param type string is right value
         */
        public function setUpSun($right)
        {
            $connection = Yii::app()->db;
            $transaction=$connection->beginTransaction();
            try
            {
               $connection->createCommand('UPDATE `category` SET `left` = `left` +2 WHERE `left` > '.$right)->execute();
               $connection->createCommand('UPDATE `category` SET `right` = `right` +2 WHERE `right` > '.$right)->execute();
               $transaction->commit();
               return true;
            }
            catch(Exception $e)
            {
               $transaction->rollBack();
               return false;
            }
        }
        
        /**
         * 升级function
         */
        public function setUpdate()
        {
            $this->result =  $this->checkFather();
        }
        
        /**
        *查询子孙
        * @param type $id
        * @return type model;
        */
        public function loadModel($id)
        {
            return  Category::model()->findByPk($id);
        }
        
        
        /**
         * 查询父亲数据
         */
        public function checkFather()
        {
            $model = Category::model()->findByPk($this->params->post);
            $father = $this->checkFid($model);
            if(!is_null($father))
            {
                $model->id = $father->id;
            }             
                return $model;
        }
        
        /**
         *检查是否为父类
         * @param type $model
         * @return type object
         */
        public function checkFid($model)
        {                
            $criteria = new CDbCriteria;
            $criteria->condition = 't.left < '.$model->left;
            $criteria->addCondition('t.right > '.$model->right);
            $criteria->order = 't.id desc';
            $criteria->limit = '1';
            $model = Category::model()->find($criteria);
            if(!is_null($model))
                return $model;
            else
                return null;        
        }


        /**
         *计算子孙
         * @param type $model
         * @return type string
         */
        public function setParent($model)
        {
            return ($model->right - $model->left - self::DEFAULTS)/2;
        }
        
        
        /**
         * 更新分类
         */
        public function saveUpdate()
        {
            $array = array();
            $session = new CHttpSession;
            $session->open();
            $session->add('model',Category::model()->findAll());
            $dbAll = $session->get('model');
            $model = $this->loadModel($this->params->post);
            $parent = $this->setParent($model);//计算子孙
            $oldFather = $this->checkFid($model);//原父亲
            $newFather = $this->loadModel($this->params->value['id']);//目标父亲对象
            if(!is_null($newFather))
                $checkFid = $this->checkFid($newFather);//计算新父亲是否存在上级父亲
            foreach($dbAll as $key=>$n)
            {
                if($n['id'] !=$model->attributes['id'])
                    $array[$key] = $n;
            }
            foreach($array as $key=>$n)
            {
                if($n['right']>$model->right)
                {
                        $array[$key]['right'] = $n['right']-2;
                        $array[$key]['left'] = $n['left']-2;
                }
            }
            var_dump($array);
            exit;
            
            /*
            if($parent == 0 && $this->params->value['id'] == '')
            {
                $this->setDownSun($oldFather->right);//回收大于父亲右值的其它分类左右值
                $this->setminiUpdate($oldFather->right-1, $model->right+1);//回收同背左右值,减2
                $this->updateFatherDown($oldFather);//旧父亲右值更新
                $right = $this->checkMax();//计算新右值
                if($right > $model->right)
                {
                    $model->left = $right+1;
                    $model->right = $right+2;
                    $model->layout = '0';
                }
            }
            elseif($oldFather->left < $newFather->right && 0 < $newFather->layout)
            {
                exit;//内部移动，先未处理
            }
            elseif($newFather->layout == 0 && 0 < $this->params->value['id'])
            {
                if(is_null($oldFather) && $newFather)//主类插入主类(pass)
                { 
                    $this->setUpSun($newFather->right-1);
                    $model->left = $newFather->right;
                    $model->right = $newFather->right+1;
                    $model->layout = ($newFather->layout+1);
                }
                elseif($oldFather->right < $newFather->right)//如果原父亲右值小于新父亲右值，只对原父亲右值进行减2（此处为由上至下，已测试pass）
                {
                    $this->setminiUpdate($oldFather->right-1, $model->right+1);//回收同背左右值,减2
                    $this->setminiUpdate($newFather->right-1,$oldFather->right+1);//回收新父亲子孙左右值,减2
                    $this->updateFatherDown($oldFather);//旧父亲右值更新
                    $this->updateFatherDownLeft($newFather);//新父亲左值更新
                    $model->left = $newFather->right -2;
                    $model->right = $newFather->right -1;
                    $model->layout = ($newFather->layout+1);
                }
                elseif($newFather->right < $oldFather->right)//如果新父亲值小于旧父亲值,对新父亲和两者之间的值进行加2（此处为由下至上，已测试pass）
                {                    
                        $this->setBigUpdate($newFather->right+2,$model->right-2);
                        $this->updateFatherDownOne($oldFather);
                        $this->updateFatherUp($newFather);//更新新父亲右值,为插入对象增加空间
                        $model->left = $newFather->right -2;
                        $model->right = $newFather->right -1;
                        $model->layout = ($newFather->layout+1);                       
                }
            }


            /*
            if($parent == 0 && $this->params->value['id'] == '')//子类更新为主类(pass)
            {                                  
                $this->setDownSun($oldFather->right);//回收大于父亲右值的其它分类左右值
                $this->setminiUpdate($oldFather->right-1, $model->right+1);//回收同背左右值,减2
                $this->updateFatherDown($oldFather);//旧父亲右值更新
                $right = $this->checkMax();//计算新右值
                if($right > $model->right)
                {
                    $model->left = $right+1;
                    $model->right = $right+2;
                    $model->layout = '0';
                }
            }
            else
            {   
                if(!is_null($checkFid) && 0 < $oldFather->layout)//同父亲平移
                {
                    if($newFather->right < $model->right)
                    {
                        $this->setBigUpdate($newFather->right+1,$model->right-1);//回收同背左右值
                        $this->updateFatherUp($newFather);
                        $model->left = $newFather->right-2;
                        $model->right = $newFather->right-1;
                    }
                    elseif($model->right < $newFather->right)
                    {
                        $this->setminiUpdate($newFather->right,$model->right+1);//回收同背左右值
                        $model->left = $newFather->left+$parent;
                        $model->right = $newFather->right+$parent;
                    }
                    $model->layout = ($newFather->layout+1);
                }
                elseif(is_null($oldFather) && $newFather && $oldFather->layout == 0)//主类插入主类(pass)
                { 
                    $this->setUpSun($newFather->right-1);
                    $model->left = $newFather->right;
                    $model->right = $newFather->right+1;
                    $model->layout = ($newFather->layout+1);
                }
                elseif($oldFather->right < $newFather->right && $oldFather->layout == 0)//如果原父亲右值小于新父亲右值，只对原父亲右值进行减2（此处为由上至下，已测试pass）
                {
                    $this->setminiUpdate($oldFather->right-1, $model->right+1);//回收同背左右值,减2
                    $this->setminiUpdate($newFather->right-1,$oldFather->right+1);//回收新父亲子孙左右值,减2
                    $this->updateFatherDown($oldFather);//旧父亲右值更新
                    $this->updateFatherDownLeft($newFather);//新父亲左值更新
                    $model->left = $newFather->right -2;
                    $model->right = $newFather->right -1;
                    $model->layout = ($newFather->layout+1);
                }
                elseif($newFather->right < $oldFather->right && $oldFather->layout == 0)//如果新父亲值小于旧父亲值,对新父亲和两者之间的值进行加2（此处为由下至上，已测试pass）
                {                    
                        $this->setBigUpdate($newFather->right+2,$model->right-2);
                        $this->updateFatherDownOne($oldFather);
                        $this->updateFatherUp($newFather);//更新新父亲右值,为插入对象增加空间
                        $model->left = $newFather->right -2;
                        $model->right = $newFather->right -1;
                        $model->layout = ($newFather->layout+1);                       
                }
                

            }*/
                $model->id = $this->params->post;
                $model->name = $this->params->value['name'];
                $model->attributes=$model;
                if($model->save())
                    (string)$this->result = $model->id;
        }
        
        
        /*
         *差值减法
         */
        public function setminiUpdate($new,$old)
        {
            $params = array();
            $model = Yii::app()->db->createCommand('SELECT * FROM `category` WHERE `right` BETWEEN '.$old.' AND '.$new.'')->queryAll();
            foreach($model as $key)
            {
                $params[] = $key['id'];
            }
                $params = implode(',',$params);
                if(0 < strlen($params))
                    Yii::app()->db->createCommand('UPDATE `category` SET `left` = `left` -2,`right` = `right` -2 WHERE id in('.$params.') ')->execute(); 
        }
        
        /*
         *差值加法
         */
        public function setBigUpdate($new,$old)
        {
            $params = array();
            $model = Yii::app()->db->createCommand('SELECT * FROM `category` WHERE `right` BETWEEN '.$new.' AND '.$old.'')->queryAll(); 
            foreach($model as $key)
            {
                $params[] = $key['id'];
            }
            $params = implode(',',$params);
            if(0 < strlen($params))
                Yii::app()->db->createCommand('UPDATE `category` SET `left` = `left` +2,`right` = `right` +2 WHERE id in('.$params.') ')->execute();          
        }
        

        
        public function updateFatherUp($model)
        {
            $model->right = $model->right +2;
            $model->attributes = $model;
            if($model->save())
                return $model;
        }
        
        public function updateFatherDownOne($model)
        {
             $model->left = $model->left+2;
             $model->attributes = $model;
             if($model->save())
                return true;
        }
        
        public function updateFatherDownLeft($model)
        {
             $model->left = $model->left-2;
             $model->attributes = $model;
             if($model->save())
                return true;
        }
        
        public function updateFatherDown($model)
        {
             $model->right = $model->right -2;
             $model->attributes = $model;
             if($model->save())
                return true;
        }
        
        
        
        /**
         *返回操作结果
         * @return type boolean or string
         */
        public function run()
        {
            if(!is_null($this->result))
                return $this->result;
        }
        
       

}

